package net.lastcoder.web.filereceiver;

import net.lastcoder.ifserver.Globals;
import net.lastcoder.ifserver.Server;
import net.lastcoder.ifserver.util.Md5;
import net.lastcoder.ifserver.web.WebManager;
import net.lastcoder.ifserver.plugin.Plugin;
import net.lastcoder.ifserver.plugin.PluginManager;
import net.lastcoder.ifserver.util.TextUtils;

import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.handler.AbstractHandler;
import org.json.JSONException;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;

import javax.servlet.ServletException;
import javax.servlet.ServletInputStream;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * auth: WenYF
 * date: 2017/2/6
 */
public class FileReceiverPlugin extends AbstractHandler implements Plugin {
    private static final Logger Log = LoggerFactory.getLogger(FileReceiverPlugin.class);

    public static FileReceiverPlugin instance;

    private String fileDir;
    public FileReceiverPlugin() throws Throwable {
        File file = new File(Globals.getHomeDirectory() + File.separator + "webapp" + File.separator + "files");
        if (!file.exists()) {
            if (!file.mkdirs()) {
                throw new Throwable(file.getAbsolutePath() + " not make error.");
            }
        }

        fileDir = file.getAbsolutePath();
    }

    @Override
    public void initializePlugin(PluginManager manager, File pluginDirectory) {
        WebManager.getInstance().addHandler("/file", this);
    }

    @Override
    public void destroyPlugin() {
        WebManager.getInstance().removeHandler("/file");
    }

    @Override
    public void handle(String s, Request request, HttpServletRequest httpServletRequest
            , HttpServletResponse httpServletResponse) throws IOException, ServletException {
        String retContent = "";
        JSONObject json = new JSONObject();
        switch (request.getMethod()) {
            case "POST": {
                // 上传
                String md5 = request.getHeader("md5");
                String filename = request.getHeader("filename");
                String plugin = request.getHeader("plugin");
                if ("yes".equalsIgnoreCase(plugin)) {
                    // 上传插件
                    InputStream is = request.getInputStream();
                    PluginManager pluginManager = Server.getInstance().getPluginManager();
                    String pluginName = filename.split("\\.")[0];
                    pluginManager.unloadPlugin(pluginName);
                    boolean ret = pluginManager.installPlugin(is, filename);
                    if (ret) {
                        Log.debug("upload plugin success.");
                        try {
                            json.put("errcode", 0);
                        } catch (JSONException e) {
                            e.printStackTrace();
                        }
                    } else {
                        Log.debug("upload plugin failed.");
                        try {
                            json.put("errcode", 400);
                            json.put("retmsg", "install error.");
                        } catch (JSONException e) {
                            e.printStackTrace();
                        }
                    }
                } else if (TextUtils.isEmpty(md5) || TextUtils.isEmpty(filename)) {
                    try {
                        json.put("retcode", 400);
                        json.put("retmsg", "md5 is empty or filename is empty");
                    } catch (JSONException e) {
                        e.printStackTrace();
                    }

                } else {
                    File file = new File(fileDir, filename);
                    if (file.exists()) {
                        file.delete();
                    }
                    file.createNewFile();
                    FileOutputStream os = new FileOutputStream(file);
                    ServletInputStream sis = request.getInputStream();

                    byte[] buffer = new byte[4096];
                    int size = -1;
                    int count = 0;
                    while ((size = sis.read(buffer)) != -1) {
                        os.write(buffer, 0, size);
                        count += size;
                    }
                    os.close();

                    String sumMd5 = Md5.sum(file.getAbsolutePath());
                    Log.debug("upload file name = " + filename);
                    Log.debug("upload file size count = " + count);
                    if (md5.equalsIgnoreCase(sumMd5)) {
                        // 上传成功
                        Log.debug("upload file md5 success.");
                        try {
                            json.put("errcode", 0);
                        } catch (JSONException e) {
                            e.printStackTrace();
                        }
                    } else {
                        // 上传失败
                        try {
                            json.put("errcode", 400);
                            json.put("retmsg", "md5 is diffrent.");
                        } catch (JSONException e) {
                            e.printStackTrace();
                        }
                    }
                }
                retContent = json.toString();

                byte[] data = retContent.getBytes("UTF-8");
                httpServletResponse.getOutputStream().write(data);
                httpServletResponse.setContentType("text/plain");
                httpServletResponse.setContentLength(data.length);

                break;
            }
            default: {
                String token = request.getHeader("token");
                if (!"wenyongfu".equals(token)) {
                    httpServletResponse.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
                    return;
                }

                // 下载
                String filename = request.getHeader("filename");

                if (TextUtils.isEmpty(filename)) {
                    try {
                        json.put("retcode", 400);
                        json.put("retmsg", "filename is empty");
                    } catch (JSONException e) {
                        e.printStackTrace();
                    }

                    retContent = json.toString();
                    byte[] data = retContent.getBytes("UTF-8");
                    httpServletResponse.getOutputStream().write(data);
                    httpServletResponse.setContentLength(data.length);
                } else {

                    File file = new File(fileDir, filename);

                    if (file.exists()) {
                        //String md5 = net.lastcoder.tools.fileupload.Md5.sum(file.getAbsolutePath());
                        ServletOutputStream sos = httpServletResponse.getOutputStream();
                        FileInputStream fis = new FileInputStream(file);

                        int size = fis.available();
                        byte[] buffer = new byte[size];
                        size = fis.read(buffer);
                        sos.write(buffer, 0, size);
                        fis.close();

                        httpServletResponse.setContentType("application/octet-stream");
                        httpServletResponse.setContentLength(size);
                    } else {
                        try {
                            json.put("errcode", 400);
                            json.put("retmsg", "file is not exist.");
                        } catch (JSONException e) {
                            e.printStackTrace();
                        }
                        retContent = json.toString();
                        byte[] data = retContent.getBytes("UTF-8");
                        httpServletResponse.getOutputStream().write(data);
                        httpServletResponse.setContentType("text/plain");
                        httpServletResponse.setContentLength(data.length);
                    }
                }
                break;
            }
        }
        httpServletResponse.setStatus(HttpServletResponse.SC_OK);

        httpServletResponse.getOutputStream().flush();
    }
}
